package org.jeecg.modules.file;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.event.ProgressEvent;
import com.aliyun.oss.event.ProgressEventType;
import com.aliyun.oss.event.ProgressListener;
import com.aliyun.oss.model.GetObjectRequest;
import org.jeecg.common.api.vo.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.io.*;
import java.net.URL;

@RestController
@RequestMapping("/api/oss/file")
public class GetObjectProgressListener implements ProgressListener {

    private static Logger logger = LoggerFactory.getLogger(GetObjectProgressListener.class);

    private long bytesRead = 0;
    private long totalBytes = -1;

    @PostMapping("/download")
    public Result downloadFile(@RequestParam(name="username",required=true) String username,
                                 @RequestParam(name="module",required=true) String module) {
        // 获取用户名
//        String username = (String) map.get("username");

        // 创建OSSClient实例（OSS客户端实例）
        OSS ossClient = new OSSClientBuilder().build(OssConfig.ENDPOINT,
                OssConfig.KEY_ID, OssConfig.KEY_SECRET);
        // 拼接文件名称
        String fileName = username;

        // 拼接oss中文件的路径avatar/lixianhe.webp
        String objectName = module + "/" + fileName;
        // 目标文件下载位置
        String pathName = "E:\\Downloads\\" + fileName;

        // 下载是否成功
        boolean downloadIsSucceed = false;

        try {
            // 下载文件的同时指定了进度条参数。
            ossClient.getObject(new GetObjectRequest(OssConfig.BUCKET_NAME, objectName).
                    withProgressListener(new GetObjectProgressListener()), new File(pathName));
            downloadIsSucceed = true;
        } catch (OSSException oe) {
            logger.info("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            logger.info("Error Message:" + oe.getErrorMessage());
            logger.info("Error Code:" + oe.getErrorCode());
            logger.info("Request ID:" + oe.getRequestId());
            logger.info("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            logger.info("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            logger.info("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }

        if (downloadIsSucceed) {
            return Result.ok("下载成功");
        } else {
            return Result.error("下载失败");
        }
    }

    @Override
    public void progressChanged(ProgressEvent progressEvent) {
        long bytes = progressEvent.getBytes();
        ProgressEventType eventType = progressEvent.getEventType();
        switch (eventType) {
            case TRANSFER_STARTED_EVENT:
                logger.info("Start to download......");
                break;
            case RESPONSE_CONTENT_LENGTH_EVENT:
                this.totalBytes = bytes;
                logger.info(this.totalBytes + " bytes in total will be downloaded to a local file");
                break;
            case RESPONSE_BYTE_TRANSFER_EVENT:
                this.bytesRead += bytes;
                if (this.totalBytes != -1) {
                    int percent = (int) (this.bytesRead * 100.0 / this.totalBytes);
                    logger.info(bytes + " bytes have been read at this time, download progress: " +
                            percent + "%(" + this.bytesRead + "/" + this.totalBytes + ")");
                } else {
                    logger.info(bytes + " bytes have been read at this time, download ratio: unknown" +
                            "(" + this.bytesRead + "/...)");
                }
                break;
            case TRANSFER_COMPLETED_EVENT:
                logger.info("Succeed to download, " + this.bytesRead + " bytes have been transferred in total");
                break;
            case TRANSFER_FAILED_EVENT:
                logger.info("Failed to download, " + this.bytesRead + " bytes have been transferred");
                break;
            default:
                break;
        }
    }

    /**
     * 预览
     * @param fileName
     * @return
     * @throws IOException
     */
    @GetMapping("/preview")
    public ResponseEntity<InputStreamResource> preview(@RequestParam(name="fileName",required=true) String fileName) throws IOException {
        // Path to the file you want to serve
        String filePath = fileName.trim();

//        File file = new File(filePath);
        File tempFile = getFile(filePath);
        // Open the file as an input stream
        InputStream inputStream = new FileInputStream(tempFile);

        // Set the content type and disposition headers
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_PDF);
        headers.setContentDispositionFormData("attachment", fileName); // or "inline"

        // Create an InputStreamResource from the input stream
        InputStreamResource inputStreamResource = new InputStreamResource(inputStream);

        // Return the ResponseEntity with headers and input stream resource
        return ResponseEntity.ok()
                .headers(headers)
                .body(inputStreamResource);
    }

    /**
     * 创建一个临时文件
     * @param url 远端文件Url
     * @return File
     */
    private File getFile(String url) {
        //对本地文件命名
        String fileName = url.substring(url.lastIndexOf("."), url.length());
        File file = null;

        URL urlfile;
        try {
            // 创建一个临时路径
            file = File.createTempFile("file", fileName);
            logger.info("tempFile:->{}",file.getAbsolutePath());
            //下载
            urlfile = new URL(url);

            try (InputStream inStream = urlfile.openStream();
                 OutputStream os =  new FileOutputStream(file)) {
                int bytesRead = 0;
                byte[] buffer = new byte[8192];
                while ((bytesRead = inStream.read(buffer, 0, 8192)) != -1) {
                    os.write(buffer, 0, bytesRead);
                }
            }
        } catch (Exception e) {
            logger.error("创建临时文件出错：-》{}",e.getMessage());
        }
        return file;
    }


}